package com.example.testproject.bean

import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.lang.Exception

/**
 *
 * @ClassName: BaseLiveData
 * @Author: android 超级兵
 * @CreateDate: 11/15/21$ 7:52 PM$
 * TODO 用于解决liveData事件粘性
 */
object BaseLiveDataBus {

    private val mapCache: MutableMap<String, BaseLiveData<Any>> by lazy { HashMap() }

    fun <T> with(
        key: String,
        isStick: Boolean = true,// 是否开启粘性,默认粘性[true]
    ) = let {
        if (!mapCache.containsKey(key)) {
            mapCache[key] = BaseLiveData(isStick)
        }
        mapCache[key]!!
    }

    class BaseLiveData<T>(private var isStick: Boolean) : MutableLiveData<T>() {

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
            Log.i("szjIsStick", "$isStick")
            // true粘性 false不粘性
            if (!isStick) {
                hook(observer)
            }
        }

        private fun hook(observer: Observer<in T>) {
            // 得到liveData的class
            val liveDataClass = LiveData::class.java

            /*
             * 拿到 LiveData.mObservers
             * 作者:android 超级兵
             * 创建时间: 11/15/21 8:42 PM
             *  private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
             *  new SafeIterableMap<>();
             */
            val mObserversField = liveDataClass.getDeclaredField("mObservers")
            // 私有属性也能使用
            mObserversField.isAccessible = true

            val map = mObserversField.get(this@BaseLiveData)

            // 获取到map对象
            val mapClass = map.javaClass

            // 调用 SafeIterableMap.get() 得到具体的值
            val getMethod = mapClass.getDeclaredMethod("get", Any::class.java)
            // 私有属性也能使用
            getMethod.isAccessible = true

            /*
             * 作者:android 超级兵
             * 创建时间: 11/15/21 8:08 PM
             * TODO
             *   参数一:需要改变的类
             *   参数二:方法的参数

             */
            val invoke = getMethod.invoke(map, observer)

            try {
                if (invoke != null && invoke is Map.Entry<*, *>) {
                    val value = invoke.value

                    val superclass = value!!.javaClass.superclass
                    // 通过observer 获取到 mListVersion
                    val mListVersionField = superclass.getDeclaredField("mLastVersion")
                    mListVersionField.isAccessible = true

                    val versionField = liveDataClass.getDeclaredField("mVersion")
                    versionField.isAccessible = true

                    // 得到 Version 的具体值
                    val versionValue = versionField.get(this)

                    // 执行 将value复制到 Version上
                    mListVersionField.set(value, versionValue)
                }
            } catch (e: Exception) {
                Log.i("szj出错了..", e.message + "")
            }
        }
    }
}